home *** CD-ROM | disk | FTP | other *** search
/ Amiga Format CD 24 / Amiga Format AFCD24 (Feb 1998, Issue 108).iso / -in_the_mag- / emulation / macos / uae069b2.src.cpt.hqx / UAE069ß2.SRC.CPT / uae069fl2.src / gfxutil.c < prev    next >
C/C++ Source or Header  |  1997-06-25  |  10KB  |  452 lines

  1.  /* 
  2.   * UAE - The Un*x Amiga Emulator
  3.   * 
  4.   * Common code needed by all the various graphics systems.
  5.   * 
  6.   * (c) 1996 Bernd Schmidt, Ed Hanway, Samuel Devulder
  7.   */
  8.  
  9. #include "sysconfig.h"
  10. #include "sysdeps.h"
  11.  
  12. #include "config.h"
  13. #include "options.h"
  14. #include "my_memory.h"
  15. #include "custom.h"
  16. #include "keyboard.h"
  17. #include "xwin.h"
  18. #include "keybuf.h"
  19.  
  20. #define    RED     0
  21. #define    GRN    1
  22. #define    BLU    2
  23.  
  24. /*
  25.  * dither matrix
  26.  */
  27. static uae_u8 dither[4][4] =
  28. {
  29.   {0,8,2,10},
  30.   {12,4,14,6},
  31.   {3,11,1,9},
  32.   {14 /* 15 */,7,13,5}
  33. };
  34.  
  35. unsigned long doMask(int p, int bits, int shift)
  36. {
  37.     /* p is a value from 0 to 15 (Amiga color value)
  38.      * scale to 0..255, shift to align msb with mask, and apply mask */
  39.  
  40.     unsigned long val = p * 0x11111111UL;
  41.     val >>= (32 - bits);
  42.     val <<= shift;
  43.  
  44.     return val;
  45. }
  46.  
  47. void alloc_colors64k(int rw, int gw, int bw, int rs, int gs, int bs)
  48. {
  49.     int i;
  50.     for(i=0; i<4096; i++) {
  51.     int r = i >> 8;
  52.     int g = (i >> 4) & 0xF;
  53.     int b = i & 0xF;
  54.     xcolors[i] = doMask(r, rw, rs) | doMask(g, gw, gs) | doMask(b, bw, bs);
  55.     }
  56. }
  57.  
  58. static int allocated[4096];
  59. static int color_diff[4096];
  60. static int newmaxcol = 0;
  61.  
  62. void setup_maxcol(int max)
  63. {
  64.     newmaxcol = max;
  65. }
  66.  
  67. void alloc_colors256(allocfunc_type allocfunc)
  68. {
  69.     int nb_cols[3]; /* r,g,b */
  70.     int maxcol = newmaxcol == 0 ? 256 : newmaxcol;
  71.     int i,j,k,l,t;
  72.  
  73.     xcolnr *map;
  74.     
  75.     map = (xcolnr *)malloc(sizeof(xcolnr) * maxcol);
  76.     if(!map) {
  77.     write_log("Not enough mem for colormap!\n");
  78.     abort();
  79.     }    
  80.     
  81.     /*
  82.      * compute #cols per components
  83.      */
  84.     for(i = 1; i*i*i <= maxcol; ++i)
  85.     ;
  86.     --i;
  87.  
  88.     nb_cols[RED] = i;
  89.     nb_cols[GRN] = i;
  90.     nb_cols[BLU] = i;
  91.  
  92.     /*
  93.      * set the colormap
  94.      */
  95.     l=0;
  96.     for(i = 0; i < nb_cols[RED]; ++i) {
  97.     int r = (i * 15) / (nb_cols[RED] - 1);
  98.     for(j = 0; j < nb_cols[GRN]; ++j) {
  99.         int g = (j * 15) / (nb_cols[GRN] - 1);
  100.         for(k = 0; k < nb_cols[BLU]; ++k) { 
  101.         int b = (k * 15) / (nb_cols[BLU] - 1);
  102.         int result;
  103.         result = allocfunc(r, g, b, map + l);
  104.         l++;
  105.         }
  106.     }
  107.     }
  108. /*    printf("%d color(s) lost\n",maxcol - l);*/
  109.  
  110.     /*
  111.      * for each component compute the mapping
  112.      */
  113.     {
  114.     int diffr, diffg, diffb, maxdiff = 0, won = 0, lost;
  115.     int r, d = 8;
  116.     for(r=0; r<16; ++r) {
  117.         int cr, g, q;
  118.       
  119.         k  = nb_cols[RED]-1;
  120.         cr = (r * k) / 15;
  121.         q  = (r * k) % 15;
  122.         if(q > d && cr < k) ++cr;
  123.         diffr = abs(cr*k-r);
  124.         for(g=0; g<16; ++g) {
  125.         int cg, b;
  126.           
  127.         k  = nb_cols[GRN]-1;
  128.         cg = (g * k) / 15;
  129.         q  = (g * k) % 15;
  130.         if(q > d && cg < k) ++cg;
  131.         diffg = abs(cg*k-g);
  132.         for(b=0; b<16; ++b) {
  133.             int cb, rgb = (r<<8) | (g<<4) | b;
  134.  
  135.             k  = nb_cols[BLU]-1;
  136.             cb = (b * k) / 15;
  137.             q  = (b * k) % 15;
  138.             if(q > d && cb < k) ++cb;
  139.             diffb = abs(cb*k-b);
  140.             xcolors[rgb] = map[(cr*nb_cols[GRN]+cg)*nb_cols[BLU]+cb];
  141.             color_diff[rgb] = diffr+diffg+diffb;
  142.             if (color_diff[rgb] > maxdiff)
  143.             maxdiff = color_diff[rgb];
  144.         }
  145.         }
  146.     }
  147.     while (maxdiff > 0 && l < maxcol) {
  148.         int newmaxdiff = 0;
  149.         lost = 0; won++;
  150.         for(r = 15; r >= 0; r--) {
  151.         int cr, g, q;
  152.       
  153.         for(g = 15; g >= 0; g--) {
  154.             int cg, b;
  155.           
  156.             for(b = 15; b >= 0; b--) {
  157.             int cb, rgb = (r<<8) | (g<<4) | b;
  158.  
  159.             if (color_diff[rgb] == maxdiff) {
  160.                 int result;
  161.             
  162.                 if (l >= maxcol)
  163.                 lost++;
  164.                 else {
  165.                 result = allocfunc(r, g, b, xcolors + rgb);
  166.                 l++;
  167.                 }
  168.                 color_diff[rgb] = 0;
  169.             } else if (color_diff[rgb] > newmaxdiff)
  170.                 newmaxdiff = color_diff[rgb];
  171.             
  172.             }
  173.         }
  174.         }
  175.         maxdiff = newmaxdiff;
  176.     }
  177. /*    printf("%d color(s) lost, %d stages won\n",lost, won);*/
  178.     }
  179.     free (map);
  180. }
  181.  
  182. /*
  183.  * This dithering process works by letting UAE run internaly in 12bit
  184.  * mode and doing the dithering on the fly when rendering to the display.
  185.  * The dithering algorithm is quite fast but uses lot of memory (4*8*2^12 =
  186.  * 128Kb). I don't think that is a trouble right now, but when UAE will 
  187.  * emulate AGA and work internaly in 24bit mode, that dithering algorithm
  188.  * will need 4*8*2^24 = 512Mb. Obviously that fast algorithm will not be
  189.  * tractable. However, we could then use an other algorithm, slower, but 
  190.  * far more reasonable (I am thinking about the one that is used in DJPEG).
  191.  */
  192.  
  193. #ifndef __mac__
  194.  
  195. uae_u8 cidx[4][8*4096]; /* fast, but memory hungry =:-( */
  196.  
  197. /*
  198.  * Compute dithering structures
  199.  */
  200. void setup_greydither_maxcol(int maxcol, allocfunc_type allocfunc)
  201. {
  202.     int i,j,k,l,t;
  203.     xcolnr *map;
  204.     
  205.     for (i = 0; i < 4096; i++)
  206.     xcolors[i] = i;
  207.     
  208.     map = (xcolnr *)malloc(sizeof(xcolnr) * maxcol);
  209.     if(!map) {
  210.     write_log("Not enough mem for colormap!\n");
  211.     abort();
  212.     }    
  213.  
  214.     /*
  215.      * set the colormap
  216.      */
  217.     for(i = 0; i < maxcol; ++i) {
  218.     int c, result;
  219.     c = (15 * i + (maxcol-1)/2) / (maxcol - 1);
  220.         result = allocfunc(c, c, c, map + i);
  221.     /* @@@ check for errors */
  222.     }
  223.  
  224.     /*
  225.      * for each componant compute the mapping
  226.      */
  227.     for(i=0;i<4;++i) {
  228.     for(j=0;j<4;++j) {
  229.         int r, d = dither[i][j]*17;
  230.         for(r=0; r<16; ++r) {
  231.         int g;
  232.         for(g=0; g<16; ++g) {
  233.             int  b;
  234.             for(b=0; b<16; ++b) {
  235.             int rgb = (r<<8) | (g<<4) | b;
  236.             int c,p,q;
  237.             
  238.             c = (77  * r + 
  239.                  151 * g + 
  240.                  28  * b) / 15; /* c in 0..256 */
  241.             
  242.             k = maxcol-1;  
  243.             p = (c * k) / 256;
  244.             q = (c * k) % 256;
  245.             if(q /*/ k*/> d /*/ k*/ && p < k) ++p;
  246. /* sam:                      ^^^^^^^ */
  247. /*  It seems that produces better output */
  248.             cidx[i][rgb + (j+4)*4096] = 
  249.                 cidx[i][rgb + j*4096] = map[p];
  250.             }
  251.         }
  252.         }
  253.     }
  254.     }
  255.     free (map);
  256. }
  257.  
  258. void setup_greydither(int bits, allocfunc_type allocfunc)
  259. {
  260.     setup_greydither_maxcol(1 << bits, allocfunc);
  261. }
  262.  
  263. void setup_dither(int bits, allocfunc_type allocfunc)
  264. {
  265.     int nb_cols[3]; /* r,g,b */
  266.     int maxcol = 1 << bits;
  267.     int i,j,k,l,t;
  268.  
  269.     xcolnr *map;
  270.     int *redvals, *grnvals, *bluvals;
  271.     
  272.     map = (xcolnr *)malloc(sizeof(xcolnr) * maxcol);
  273.     if(!map) {
  274.     write_log("Not enough mem for colormap!\n");
  275.     abort();
  276.     }    
  277.  
  278.     for (i = 0; i < 4096; i++)
  279.     xcolors[i] = i;
  280.     
  281.     /*
  282.      * compute #cols per components
  283.      */
  284.     for(i = 1; i*i*i <= maxcol; ++i)
  285.     ;
  286.     --i;
  287.  
  288.     nb_cols[RED] = i;
  289.     nb_cols[GRN] = i;
  290.     nb_cols[BLU] = i;
  291.  
  292.     if(nb_cols[RED]*(++i)*nb_cols[BLU] <= maxcol) {
  293.     nb_cols[GRN] = i;
  294.     if((i)*nb_cols[GRN]*nb_cols[BLU] <= maxcol) nb_cols[RED] = i;
  295.     }
  296.  
  297.     redvals = (int *)malloc(sizeof(int) * maxcol);
  298.     grnvals = redvals + nb_cols[RED];
  299.     bluvals = grnvals + nb_cols[GRN];
  300.     /*
  301.      * set the colormap
  302.      */
  303.     l=0;
  304.     for(i = 0; i < nb_cols[RED]; ++i) {
  305.     int r = (i * 15) / (nb_cols[RED] - 1);
  306.     redvals[i] = r;
  307.     for(j = 0; j < nb_cols[GRN]; ++j) {
  308.         int g = (j * 15) / (nb_cols[GRN] - 1);
  309.         grnvals[j] = g;
  310.         for(k = 0; k < nb_cols[BLU]; ++k) { 
  311.         int b = (k * 15) / (nb_cols[BLU] - 1);
  312.         int result;
  313.         bluvals[k] = b;
  314.         result = allocfunc(r, g, b, map + l);
  315.         l++;
  316.         }
  317.     }
  318.     }
  319. /*    fprintf(stderr, "%d color(s) lost\n",maxcol - l);*/
  320.  
  321.     /*
  322.      * for each component compute the mapping
  323.      */
  324.     {
  325.     int r;
  326.     for(r=0; r<16; ++r) {
  327.         int g;
  328.         for(g=0; g<16; ++g) {
  329.         int b;
  330.         for(b=0; b<16; ++b) {
  331.             int rederr = 0, grnerr = 0, bluerr = 0;
  332.             int rgb = (r<<8) | (g<<4) | b;
  333.  
  334.             for(i=0;i<4;++i) for(j=0;j<4;++j) {
  335.             int d = dither[i][j];
  336.             int cr, cg, cb, k, q;
  337. #if 0 /* Slightly different algorithm. Needs some tuning. */
  338.             k  = nb_cols[RED]-1;
  339.             cr = r * k / 15;
  340.             q  = r * k - 15*cr;
  341.             if (cr < 0) cr = 0;
  342.             else
  343.                 if(q / k > d / k && rederr <= 0) ++cr;
  344.             if (cr > k) cr = k;
  345.             rederr += redvals[cr]-r;
  346.           
  347.             k  = nb_cols[GRN]-1;
  348.             cg = g * k / 15;
  349.             q  = g * k - 15*cg;
  350.             if (cg < 0) cg = 0;
  351.             else
  352.                 if (q / k > d / k && grnerr <= 0) ++cg;
  353.             if (cg > k) cg = k;
  354.             grnerr += grnvals[cg]-g;
  355.  
  356.             k  = nb_cols[BLU]-1;
  357.             cb = b * k / 15;
  358.             q  = b * k - 15*cb;
  359.             if (cb < 0) cb = 0;
  360.             else
  361.                 if (q / k > d / k && bluerr <= 0) ++cb;
  362.             if (cb > k) cb = k;
  363.             bluerr += bluvals[cb]-b;
  364. #else
  365.             k  = nb_cols[RED]-1;
  366.             cr = r * k / 15;
  367.             q  = r * k - 15*cr;
  368.             if (cr < 0) cr = 0;
  369.             else
  370.                 if(q /*/ k*/ > d /*/ k*/) ++cr;
  371.             if (cr > k) cr = k;
  372.           
  373.             k  = nb_cols[GRN]-1;
  374.             cg = g * k / 15;
  375.             q  = g * k - 15*cg;
  376.             if (cg < 0) cg = 0;
  377.             else
  378.                 if (q /*/ k*/ > d /*/ k*/) ++cg;
  379.             if (cg > k) cg = k;
  380.  
  381.             k  = nb_cols[BLU]-1;
  382.             cb = b * k / 15;
  383.             q  = b * k - 15*cb;
  384.             if (cb < 0) cb = 0;
  385.             else
  386.                 if (q /*/ k*/ > d /*/ k*/) ++cb;
  387.             if (cb > k) cb = k;
  388. #endif
  389.             cidx[i][rgb + (j+4)*4096] = cidx[i][rgb + j*4096] = map[(cr*nb_cols[GRN]+cg)*nb_cols[BLU]+cb];
  390.             }
  391.         }
  392.         }
  393.     }
  394.     }
  395.     free (map);
  396. }
  397.  
  398. #if !defined X86_ASSEMBLY
  399. /*
  400.  * Dither the line.
  401.  * Make sure you call this only with (len & 3) == 0, or you'll just make
  402.  * yourself unhappy.
  403.  */
  404.  
  405. void DitherLine(uae_u8 *l, uae_u16 *r4g4b4, int x, int y, uae_s16 len, int bits)
  406. {
  407.     uae_u8 *dith = cidx[y&3]+(x&3)*4096;
  408.     uae_u8 d = 0;
  409.     int bitsleft = 8;
  410.     
  411.     if(bits == 8) {    
  412.     while(len>0) {
  413.         *l++ = dith[0*4096 + *r4g4b4++];
  414.         *l++ = dith[1*4096 + *r4g4b4++];
  415.         *l++ = dith[2*4096 + *r4g4b4++];
  416.         *l++ = dith[3*4096 + *r4g4b4++];
  417.         len -= 4;
  418.     }
  419.     return;
  420.     }
  421.  
  422.     while(len) {
  423.     int v;
  424.     v = dith[0*4096 + *r4g4b4++];
  425.     bitsleft -= bits;
  426.     d |= (v << bitsleft);
  427.     if (!bitsleft)
  428.         *l++ = d, bitsleft = 8, d = 0;
  429.     
  430.     v = dith[1*4096 + *r4g4b4++];
  431.     bitsleft -= bits;
  432.     d |= (v << bitsleft);
  433.     if (!bitsleft)
  434.         *l++ = d, bitsleft = 8, d = 0;
  435.     
  436.     v = dith[2*4096 + *r4g4b4++];
  437.     bitsleft -= bits;
  438.     d |= (v << bitsleft);
  439.     if (!bitsleft)
  440.         *l++ = d, bitsleft = 8, d = 0;
  441.     
  442.     v = dith[3*4096 + *r4g4b4++];
  443.     bitsleft -= bits;
  444.     d |= (v << bitsleft);
  445.     if (!bitsleft)
  446.         *l++ = d, bitsleft = 8, d = 0;
  447.     len -= 4;
  448.     }
  449. }
  450. #endif
  451. #endif // __mac__
  452.